package com.launch.timer;



import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * @author ennian
 * 延时任务
 */
public  class LaunchWheelTimeout implements TimeOut {



    // 初始化
    public static final int STATE_INIT = 0 ;
    // 取消状态
    public static final int STATE_CANCELED = 1 ;

    public static final int STATE_EXPIRED = 2 ;
    public volatile int state = STATE_INIT ;

    AtomicIntegerFieldUpdater<LaunchWheelTimeout> STATE_UPDATER = AtomicIntegerFieldUpdater.newUpdater(LaunchWheelTimeout.class,"state") ;

    private final LaunchWheelTimer timer ;
    private final TimerTask task ;

    public final long deadline ;

    // 在添加WheelTimeout任务之前使用Worker.transferTimeoutsToBuckets()计算出剩余的圈
    long remainingRounds ;

    // 双向链表 仅工作线程执行操作
    LaunchWheelTimeout next ;
    LaunchWheelTimeout prev ;

    // 添加到哪个桶中
   LaunchWheelBucket bucket ;

    public LaunchWheelTimeout(LaunchWheelTimer timer, TimerTask task, long deadline) {
        this.timer = timer;
        this.task = task;
        this.deadline = deadline;
    }

    // 变更任务状态
    public boolean CASState(int expected , int state){
        final boolean casResult = STATE_UPDATER.compareAndSet(this, expected, state);
        return casResult ;
    }



    @Override
    public Timer timer() {
        return timer;
    }

    @Override
    public TimerTask task() {
        return task;
    }

    @Override
    public boolean isExpired() {
        return state == STATE_EXPIRED;
    }

    @Override
    public boolean isCancelled() {
        return state == STATE_CANCELED;
    }

    @Override
    public boolean cancel() {
        //改变成取消状态
        if (!CASState(STATE_INIT,STATE_CANCELED)) return false ;
        //添加到取消任务队列中
        timer.cancelTimeOutQueue.offer(this) ;
        return true;
    }
    //到期方法
    public void expire(){
        if (!CASState(STATE_INIT,STATE_EXPIRED)) return;
        try {
            task.run(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //移除方法
    public void remove() {
         LaunchWheelBucket bucket = this.bucket;
         if (bucket!=null)
         bucket.remove(this);
    }
}
